﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace NextCore
{
    public class States
    {
        public Dictionary<string, NextState> S = new Dictionary<string, NextState>();
        public NextState Get(string id)
        {
            return S[id];
        }
        public void Add(NextState state,bool run=false){
            
            S.Add(state.Name, state);
            if (run) state.Run();
        }
        public void Run(string id)
        {
            S[id].Run();
        }
        public void Stop(string id)
        {
            S[id].End();
        }
        public void StopAll()
        {
            foreach (var k in S.Keys)
            {
                S[k].End();
            }
        }
        public void UpdateStates()
        {
            foreach (var k in S.Keys)
            {

                var s = S[k];
                if (s.Threaded == false)
                {
                    if (s.Running == true)
                    {
                        s.Update();
                    }
                }
            }
        }
        public void RenderStates()
        {
            foreach (var k in S.Keys)
            {
                var s = S[k];
                if (s.Running == true)
                {
                    s.Render();
                }
            }
        }
    }
    public class NextState
    {
        public string Name = "";
        public bool Threaded = false;
        public bool Running = false;
        public bool Paused = false;
        public Thread This = null;
        public int UpdateWait = 40;
        public bool Done = false;
        public Mutex Lock = new Mutex();
        public virtual void OnRender()
        {
        }
        public NextState(string name,bool thread = false,int wait = 40)
        {
            Name = name;
            UpdateWait = wait;
            Threaded = true;
        }
        public void End()
        {
            if (Done) return;
            if (Threaded)
            {
                Lock.WaitOne();
                if (This.ThreadState != ThreadState.Aborted)
                {
                    This.Abort();
                    This = null;
                }
                Running = false;
                Paused = false;
                Done = true;
                Lock.ReleaseMutex();
            }
            else
            {
                Done = true;
                Running = false;
                Paused = false;
                return;
            }
        }
        public void Run()
        {
            Running = true;
            Paused = false;
            Done = false;

            if (Threaded)
            {
                This = new Thread(new ThreadStart(Update));
                This.Priority = ThreadPriority.Normal;
                This.Start();

            }
           
            Lock.WaitOne();
            OnRun();
            Lock.ReleaseMutex();
        }
        public void Update()
        {
            if (This != null)
            {
                while (true)
                {
                    if (This == null) return;
                    if (Done == true)
                    {
                        if (This == null) return;
                        if (This.ThreadState != ThreadState.Aborted)
                        {
                            This.Abort();
                            This = null;

                            return;
                        }
                    }
                    if (Paused == false && Running == true)
                    {
                        Lock.WaitOne();
                        OnUpdate();
                        Lock.ReleaseMutex();
                        System.Threading.Thread.Sleep(UpdateWait);
                        
                    }
                    else
                    {
                        System.Threading.Thread.Sleep(UpdateWait * 4);
                    }

                    }
            }
            else
            {
                OnUpdate();
            }
        }
        public virtual void OnUpdate()
        {
        }
        public void Pause()
        {
            Lock.WaitOne();
            Running = false;
            Paused = true;
            OnPause();
            Lock.ReleaseMutex();
        }
        public void Resume()
        {
            Lock.WaitOne();
            Paused = false;
            Running = true;
            OnResume();
            Lock.ReleaseMutex();
        }
        public virtual void OnRun()
        {
        }
        public virtual void OnPause()
        {
        }
        public virtual void OnResume()
        {

        }
        public void Render()
        {
            Lock.WaitOne();
            OnRender();
            Lock.ReleaseMutex();
        }
    }
}
